home *** CD-ROM | disk | FTP | other *** search
/ PC-Blue - MS DOS Public Domain Library / PC-Blue MS-DOS Public Domain Library - NYACC.iso / vol194 / kermasm.arc / MSSEND.ASM < prev    next >
Encoding:
Assembly Source File  |  1985-11-14  |  29.6 KB  |  1,011 lines

  1. ; Edit history:
  2. ;
  3. ; [v2.28]
  4. ; Make packlen less conservative so we can send bigger packets.
  5. ;     (from Edgar Butt, Univ. of Md.)
  6. ; Make ack's with incorrect sequence number update the retry counter
  7. ; like a nak would; don't increment the retry count when a nak is
  8. ; found for the expected packet + 1, since this is the same as
  9. ; an ack.
  10. ; Moved handling of ack/nak to a subroutine and took out a ton
  11. ; of repeated code (motivated by a suggestion from Edgar Butt).
  12. ; JD 1 May 1985
  13. ;
  14.     public    spar, rpar, error, error1, nout, send, flags, trans, pack
  15.     public    dodec, doenc, curchk, inichk, packlen, send11, dtrans
  16.     include msdefs.h    
  17.  
  18. spmin    equ    20        ; Minimum packet size.
  19. spmax    equ    94        ; Maximum packet size.
  20.  
  21. datas     segment    public 'datas'
  22.     extrn    buff:byte, data:byte, fcb:byte, cpfcb:byte, filbuf:byte
  23.     extrn    decbuf:byte, chrcnt:word, bufpnt:word, comand:byte
  24.     extrn    rptq:byte, origr:byte, rptct:byte, rptval:byte
  25.  
  26. flags    flginfo    <>
  27. trans    trinfo    <>
  28. dtrans    trinfo    <>            ; default trans info
  29. pack    pktinfo <>
  30. crlf    db    cr,lf,'$'
  31. ender    db    bell,bell,'$'             ;  [4]
  32. erms14  db    '?Unable to receive an acknowledgment from the host$'
  33. erms15  db    '?Unable to find file$'
  34. erms20    db    'Unable to send init packet$'
  35. erms21    db    'Unable to send file header$'
  36. erms22    db    'Unable to send data$'
  37. erms23    db    'Unable to send end-of-file packet$'
  38. erms24    db    'Unable to send break packet$'
  39. infms2  db    cr,'             Sending: In progress$'
  40. infms3  db    'Completed$'
  41. infms4  db    'Failed$'
  42. infms6  db    'Interrupted$'
  43. infms7    db    cr,' Percent transferred: 100%$'
  44. remmsg1    db    'Kermit-MS: File not found$'
  45. filhlp  db      ' Input file spec (possibly wild) $'
  46. filmsg    db    ' File name to use on target system or confirm with'
  47.     db    ' a carriage return $'
  48.  
  49. curchk    db    0        ; Use to store checksum length.
  50. inichk    db    1        ; Original or set checksum length.
  51. chrptr  dw    ?        ; Position in character buffer.
  52. fcbpt    dw    ?        ; Position in FCB.
  53. datptr  dw    ?        ; Position in packet data buffer.
  54. siz    dw    ?        ; Size of data from gtchr.
  55. temp    dw    0
  56. temp4    dw    0
  57. sendas    dw    50 dup(0)    ; Buffer for file name.
  58. difnam    db    0        ; Send under different name?
  59. difsiz    db    0        ; Size of new file name.
  60. asmsg    db    '  as  $'
  61. filopn    db    0        ; Says if disk file is open.
  62. datas    ends
  63.  
  64. code    segment    public
  65.     extrn serini:near, serrst:near, comnd:near, init:near
  66.     extrn spack:near, rpack:near, gtnfil:near, gtchr:near
  67.     extrn getfil:near, clrfln:near, nppos:near, rprpos:near
  68.     extrn erpos:near, rtpos:near, cxmsg:near, stpos:near
  69.     extrn encode:near, nulref:near, decode:near, nulr:near
  70.     extrn errpack:near, updrtr:near, clrmod:near, fcbcpy:near
  71.     extrn perpos:near, prtfn:near
  72.     assume    cs:code,ds:datas
  73.  
  74. ;    This routine sets up the data for init packet (either the
  75. ;    Send_init or ACK packet).
  76.  
  77. RPAR    PROC    NEAR
  78.     mov ah,trans.rpsiz    ; Get the receive packet size.
  79.     add ah,' '        ; Add a space to make it printable.
  80.     mov [bx],ah        ; Put it in the packet.
  81.     mov ah,trans.rtime    ; Get the receive packet time out.
  82.     add ah,' '        ; Add a space.
  83.     mov 1[bx],ah        ; Put it in the packet.
  84.     mov ah,trans.rpad    ; Get the number of padding chars.
  85.     add ah,' '
  86.     mov 2[bx],ah        ; Put it in the packet.
  87.     mov ah,trans.rpadch    ; Get the padding char.
  88.     add ah,100O        ; Uncontrol it.
  89.     and ah,7FH
  90.     mov 3[bx],ah        ; Put it in the packet.
  91.     mov ah,trans.reol    ; Get the EOL char.
  92.     add ah,' '
  93.     mov 4[bx],ah        ; Put it in the packet.
  94.     mov ah,trans.rquote    ; Get the quote char.
  95.     mov 5[bx],ah        ; Put it in the packet.
  96.     mov ah,trans.ebquot    ; Get 8-bit quote char. [21b]
  97.     mov 6[bx],ah        ; Add it to the packet. [21b] 
  98.     mov ah,trans.chklen    ; Length of checksum.
  99.     add ah,48        ; Make into a real digit.
  100.     mov 7[bx],ah
  101.     mov ah,rptq        ; Repeat quote char.
  102.     cmp ah,0        ; Null means no.
  103.     jne rpar0
  104.     mov ah,' '        ; Send a blank instead.
  105. rpar0:    mov 8[bx],ah
  106.     mov ah,09H        ; Nine pieces of data.
  107.     ret
  108. RPAR    ENDP
  109.  
  110. ; This routine reads in all the send init packet information.
  111. ; Enter with BX/ packet address, AX/ packet length
  112. ; This could probably be done much more legibly if it were table
  113. ; driven, but I'm afraid to touch it...
  114.  
  115. SPAR    PROC    NEAR
  116.     cmp ax,1
  117.     jge sparx
  118.     mov ah,dspsiz        ; Data not supplied by host, use default.
  119.     jmp sparx2
  120. sparx:    mov temp4,ax        ; Save the number of arguments.
  121.     mov ah,trans.spsiz
  122.     cmp ah,dspsiz        ; Is current value the default?
  123.     jne sparx2        ; No, assume changed by user.
  124.     mov ah,[bx]        ; Get the max packet size.
  125.     sub ah,' '        ; Subtract a space.
  126.     cmp ah,spmin        ; Can't be below the minimum.
  127.     jge sparx1
  128.     mov ah,spmin
  129.     jmp sparx2
  130. sparx1:    cmp ah,spmax        ; Or above the maximum.
  131.     jle sparx2
  132.     mov ah,spmax
  133. sparx2:    mov trans.spsiz,ah    ; Save it.
  134.     mov ax,temp4
  135.     mov ah,dtrans.stime    ; pick up default stime
  136.     cmp al,2        ; Fewer than two pieces?
  137.     jl spar02        ; yes, use default
  138. spar0:    cmp ah,dstime        ; Is current value the default?
  139.     jne spar02        ; No, assume changed by user.
  140.     mov ah,1[bx]        ; Get the timeout value.
  141.     sub ah,' '        ; Subtract a space.
  142.     cmp ah,0
  143.     ja spar01        ; Must be non-negative.
  144.     mov ah,0
  145. spar01:    cmp ah,trans.rtime    ; Same as other side's timeout.
  146.     jne spar02
  147.     add ah,5        ; If so, make it a little different.
  148. spar02:    mov trans.stime,ah    ; Save it.
  149.     mov ax,temp4
  150.     mov ah,dtrans.spad    ; get default send padding
  151.     cmp al,3        ; Fewer than three pieces?
  152.     jl spar11        ; yes, use default
  153. spar1:    cmp ah,dspad        ; Is current value the default?
  154.     jne spar11        ; No, assume changed by user.
  155.     mov ah,2[bx]        ; Get the number of padding chars.
  156.     sub ah,' '
  157.     cmp ah,0
  158.     ja spar11        ; Must be non-negative.
  159.     mov ah,0
  160. spar11:    mov trans.spad,ah
  161.     mov ax,temp4
  162.     mov ah,dtrans.spadch    ; pick up default send pad character
  163.     cmp al,4        ; Fewer than four pieces?
  164.     jl spar21
  165. spar2:    cmp ah,dspadc        ; Is current value the default?
  166.     jne spar21        ; No, assume changed by user.
  167.     mov ah,3[bx]        ; Get the padding char.
  168.     add ah,100O        ; Re-controlify it.
  169.     and ah,7FH
  170.     cmp ah,del        ; Delete?
  171.     je spar21        ; Yes, then it's OK.
  172.     cmp ah,0
  173.     jge spar20
  174.     mov ah,0        ; Below zero is no good.
  175.     jmp spar21        ; Use zero (null).
  176. spar20:    cmp ah,31        ; Is it a control char?
  177.     jle spar21        ; Yes, then OK.
  178.     mov ah,0        ; No, use null.
  179. spar21:    mov trans.spadch,ah
  180.     mov ax,temp4
  181.     mov ah,dtrans.seol    ; get default send eol char
  182.     cmp al,5        ; Fewer than five pieces?
  183.     jl spar31        ; yes, use default
  184. spar3:    cmp ah,dseol        ; Is current value the default?
  185.     jne spar31        ; No, assume changed by user.
  186.     mov ah,4[bx]        ; Get the EOL char.
  187.     sub ah,' '
  188.     cmp ah,0
  189.     jge spar30        ; Cannot be negative.
  190.     mov ah,cr        ; If it is, use default of carriage return.
  191.     jmp spar31
  192. spar30:    cmp ah,31        ; Is it a control char?
  193.     jle spar31        ; Yes, then use it.
  194.     mov ah,cr        ; Else, use the default.
  195. spar31:    mov trans.seol,ah
  196.     mov ax,temp4
  197.     mov ah,dtrans.squote    ; send quote
  198.     cmp al,6        ; Fewer than six pieces?
  199.     jl spar41
  200. spar4:    cmp ah,dsquot        ; Is current value the default?
  201.     jne spar41        ; No, assume changed by user.
  202.     mov ah,5[bx]        ; Get the quote char.
  203.     cmp ah,' '        ; Less than a space?
  204.     jge spar40
  205.     mov ah,dsquot        ; Yes, use default.
  206.     jmp spar41
  207. spar40:    cmp ah,'~'        ; Must also be less then a tilde.
  208.     jle spar41
  209.     mov ah,dsquot        ; Else, use default.
  210. spar41:    mov trans.squote,ah
  211.     cmp al,7        ; Fewer than seven pieces? [21b begin]
  212.     jge spar5
  213.     mov trans.ebquot,'Y'    ; Data not supplied by host, use default.
  214.     jmp spar51
  215. spar5:    mov ah,6[bx]        ; Get other sides 8-bit quote request.
  216.     call doquo        ; And set quote char.  [21b end]
  217. spar51:    cmp al,8        ; Fewer than eight pieces?
  218.     jge spar6
  219.     mov trans.chklen,1
  220.     jmp spar61
  221. spar6:    mov ah,inichk
  222.     mov trans.chklen,ah    ; Checksum length we really want to use.
  223.     mov ah,7[bx]        ; Get other sides checksum length.
  224.     call dochk        ; Determine what size to use.
  225. spar61:    cmp al,9        ; Fewer than nine pieces?
  226.     jge spar7
  227.     mov rptq,0
  228.     ret
  229. spar7:    mov ah,8[bx]        ; Get other sides repeat count prefix.
  230.     mov ch,drpt
  231.     mov rptq,0
  232.     call dorpt
  233.     ret
  234. SPAR    ENDP
  235.  
  236. ; Set 8-bit quote character based on my capabilities and the other
  237. ; Kermit's request.   [21b]
  238.  
  239. DOQUO    PROC    NEAR
  240.     cmp trans.ebquot,'N'    ; Can I do 8-bit quoting at all?
  241.     je dq3            ; No - so forget it.
  242.     cmp trans.ebquot,'Y'    ; Can I do it if requested?
  243.     jne dq0            ; No - it's a must that I do it.
  244.     mov trans.ebquot,ah    ; Do whatever he wants.
  245.     jmp dq1
  246. dq0:    cmp ah,'Y'        ; I need quoting - can he do it?
  247.     je dq1            ; Yes - then all is settled.
  248.     cmp ah,'N'        ; No - then don't quote.
  249.     je dq3
  250.     cmp ah,trans.ebquot    ; Both need quoting - chars must match.
  251.     jne dq3
  252. dq1:    mov ah,trans.ebquot
  253.     cmp ah,'Y'        ; If Y or N, don't validate prefix.
  254.     je dq2
  255.     cmp ah,'N'
  256.     je dq2
  257.     call prechk        ; Is it in range 33-62, 96-126?
  258.      mov ah,'Y'        ; Failed, don't do quoting.
  259.      nop
  260.     cmp ah,trans.rquote    ; Same prefix?
  261.     je dq3            ; Not allowed, so don't do quoting. 
  262.     cmp ah,trans.squote    ; Same prefix here?
  263.     je dq3            ; This is illegal too.
  264.     mov trans.ebquot,ah    ; Remember what we decided on.
  265. dq2:    ret
  266. dq3:    mov trans.ebquot,'N'    ; Quoting will not be done.
  267.     ret
  268. DOQUO    ENDP
  269.  
  270. ; Check if prefix in AH is in the proper range: 33-62, 96-126. 
  271. ; RSKP if so else RETURN.
  272. prechk:    cmp ah,33
  273.     jge prec0        ; It's above 33.
  274.     ret
  275. prec0:    cmp ah,62
  276.     jg prec1
  277.     jmp rskp        ; And below 62.  OK.
  278. prec1:    cmp ah,96
  279.     jge prec2        ; It's above 96.
  280.     ret
  281. prec2:    cmp ah,126
  282.     jg prec3
  283.     jmp rskp        ; And below 126.  OK.
  284. prec3:    ret
  285.  
  286. ; Set checksum length. 
  287. dochk:    cmp ah,'1'        ; Must be 1, 2, or 3.
  288.     jl doc1
  289.     cmp ah,'3'
  290.     jle doc2
  291. doc1:    mov ah,'1'
  292. doc2:    sub ah,48        ; Don't want it printable.
  293.     cmp ah,trans.chklen    ; Do we want the same thing?
  294.     je dochk0        ; Yes, then we're done.
  295.     mov trans.chklen,1    ; No, use single character checksum.
  296. dochk0:    ret            ; Just return for now.
  297.  
  298. ; Set repeat count quote character.  The one used must be different than
  299. ; the control and eight-bit quote characters.  Also, both sides must 
  300. ; use the same character.
  301. dorpt:    call prechk        ; Is it in the valid range?
  302.      mov ah,0        ; No, don't use their value. 
  303.      nop
  304.     cmp ah,trans.squote    ; Same as the control quote char?
  305.     je dorpt0        ; Yes, that's illegal, no repeats.
  306.     cmp ah,trans.rquote    ; How about this one?
  307.     je dorpt0        ; No good.
  308.     cmp ah,trans.ebquot    ; Same as eight bit quote char?
  309.     je dorpt0        ; Yes, that's illegal too, no repeats.
  310.     cmp ah,ch        ; Are we planning to use the same char?
  311.     jne dorpt0        ; No, that's no good either.
  312.     mov rptq,ch        ; Use repeat quote char now.
  313. dorpt0:    ret
  314.  
  315. ;    Send command
  316.  
  317. SEND    PROC    NEAR
  318.     mov comand.cmcr,0    ; Filename must be specified.
  319.     mov difnam,0        ; Assume we'll use original filename.
  320.     mov flags.wldflg,0    ; Re-initialize every time.
  321.     mov ah,cmifi        ; Parse an input file spec.
  322.     mov dx,offset fcb    ; Give the address for the FCB.
  323.     mov bx,offset filhlp    ; Text of help message.
  324.     call comnd
  325.      jmp r            ;  Give up on bad parse.
  326.     cmp flags.wldflg,0FFH    ; Any wildcards seen?
  327.     je send1        ; Yes, get a confirm.
  328.     mov bx,offset sendas    ; See if want to send file under dif name.
  329.     mov dx,offset filmsg    ; In case user needs help.
  330.     mov ah,cmtxt
  331.     call comnd
  332.      jmp r
  333.     cmp ah,0        ; Different name supplied?
  334.     je send11        ; No - keep as it.
  335.     mov difnam,1        ; Yes - send different filename.
  336.     mov difsiz,ah        ; Remember length of new name.
  337.     jmp send11
  338. send1:  mov ah,cmcfm
  339.     call comnd        ; Get a confirm.
  340.      jmp r            ;  Didn't get a confirm.
  341. send11: mov flags.droflg,0    ; Reset flags from fn parsing. [21a]
  342.     mov flags.nmoflg,0    ; Reset flags from fn parsing. [21a]
  343.     mov ah,sfirst        ; Get the first file.
  344.     mov dx,offset fcb
  345.     int dos
  346.     cmp al,0FFH        ; Any found?
  347.     jne send12
  348.     cmp pack.state,'R'    ; was this from a remote GET?
  349.     jne sen11a        ; no, print error and continue
  350.     mov bx,offset remmsg1    ; else get error message
  351.     call errpack        ; go complain
  352.     jmp abort        ; and abort this
  353. sen11a:    mov ah,prstr
  354.     mov dx,offset crlf
  355.     int dos
  356.     mov ah,prstr
  357.     mov dx,offset erms15
  358.     int dos
  359.     ret
  360. send12: cmp flags.wldflg,0    ; Any wildcards.      [7 start]
  361.     je send16        ; Nope, so no problem.
  362.     mov bx,offset fcb    ; Remember what FCB looked like.
  363.     mov di,offset cpfcb
  364.     mov cl,37        ; Size of FCB.
  365.     call fcbcpy
  366.     mov di,offset fcb+1    ; Copy filename    from DTA to FCB.
  367.     mov bx,offset buff+1
  368.     mov cl,11
  369.     call fcbcpy                    ; [7 end]
  370. send16:    call serini        ; Initialize serial port. [14]
  371.     mov pack.pktnum,0    ; Set the packet number to zero.
  372.     mov pack.numtry,0    ; Set the number of tries to zero.
  373.     mov pack.numpkt,0     ; Set the number of packets to zero.
  374.     mov pack.numrtr,0    ; Set the number of retries to zero.
  375.     mov pack.state,'S'    ; Set the state to receive initiate.
  376.     cmp flags.remflg,0    ; remote mode?
  377.     jne send2a        ; yes, continue below.
  378.     call init        ; Clear the line and initialize the buffers.
  379.     call rtpos        ; Position cursor.
  380.     mov ax,0
  381.     call nout        ; Write the number of retries.
  382.     call stpos        ; Print status of file transfer.
  383.     mov ah,prstr        ; Be informative.
  384.     mov dx,offset infms2
  385.     int dos
  386. send2:    cmp flags.remflg,0    ; remote mode?
  387.     jne send2a        ; yes, skip printing
  388.     call nppos        ; Number of packets sent.
  389.     mov ax,pack.numpkt
  390.     call nout        ; Write the packet number.
  391. send2a:    cmp pack.state,'D'    ; Are we in the data send state?
  392.     jne send3
  393.     call sdata
  394.     jmp send2
  395. send3:  cmp pack.state,'F'    ; Are we in the file send state?
  396.     jne send4
  397.     call sfile        ; Call send file.
  398.     jmp send2
  399. send4:  cmp pack.state,'Z'    ; Are we in the EOF state?
  400.     jne send5
  401.     call seof
  402.     jmp send2
  403. send5:  cmp pack.state,'S'    ; Are we in the send initiate state?
  404.     jne send6
  405.     call sinit
  406.     jmp send2
  407. send6:  cmp pack.state,'B'    ; Are we in the eot state?
  408.     jne send7
  409.     call seot
  410.     jmp send2
  411. send7:  cmp pack.state,'C'    ; Are we in the send complete state?
  412.     jne send8
  413.     call serrst        ; Reset serial port.  [14]
  414.     cmp flags.remflg,0    ; remote mode?
  415.     jne send7a        ; yes, no printing.
  416.     cmp flags.cxzflg,0    ; completed normally?
  417.     jne send7b        ; no, don't bother with this
  418.     call perpos
  419.     mov ah,prstr
  420.     mov dx,offset infms7
  421.     int dos
  422. send7b:    call stpos
  423.     mov ah,prstr
  424.     mov dx,offset infms3    ; Plus a little cuteness.
  425.     cmp flags.cxzflg,0    ; Completed or interrupted?
  426.     je snd71        ; Ended normally.
  427.     mov dx,offset infms6    ; Say was interrupted.
  428. snd71:  int dos            ; New label. 
  429.     cmp flags.belflg,0    ; Bell desired? [17a]
  430.     je sendnb        ; [17a]
  431.     mov dx,offset ender    ; Ring them bells.   [4]
  432.     int dos
  433. sendnb:    call clrmod
  434.     call rprpos
  435. send7a:    jmp rskp
  436. send8:     call serrst        ; Reset serial port.  [14]
  437.     cmp flags.remflg,0    ; remote mode?
  438.     jne send9a        ; no, no printing.
  439.     call stpos
  440.     mov ah,prstr
  441.     mov dx,offset infms4    ; Plus a little cuteness.
  442.     int dos
  443.     cmp flags.belflg,0    ; Bell desired?  [17a]
  444.     je send9        ; No.  [17a]
  445.     mov dx,offset ender    ; Ring them bells.   [4]
  446.     int dos            ;  [4]
  447. send9:    call clrmod
  448.     call rprpos
  449. send9a:    jmp rskp
  450. SEND    ENDP
  451.  
  452.  
  453. ;    Send routines
  454.  
  455. ;    Send initiate
  456.  
  457.  
  458. SINIT    PROC    NEAR
  459.     cmp pack.numtry,imxtry    ; Have we reached the maximum number of tries?
  460.     jl sinit2
  461.     call erpos
  462.     mov dx,offset erms14
  463.     mov ah,prstr
  464.     int dos            ; Print an error message.
  465.     mov bx,offset erms20
  466.     call errpack        ; Send error packet just in case.
  467.     jmp abort        ; Change the state to abort.
  468. sinit2: inc pack.numtry        ; Save the updated number of tries.
  469.     mov bx,offset data    ; Get a pointer to our data block.
  470.     call rpar        ; Set up the parameter information.
  471.     xchg ah,al
  472.     mov ah,0
  473.     mov pack.argbk1,ax    ; Save the number of arguments.
  474.     mov ax,pack.numpkt    ; Get the packet number.
  475.     mov pack.argblk,ax
  476.     mov ah,trans.chklen
  477.     mov curchk,ah        ; Store checksum length we want to use.
  478.     mov trans.chklen,1    ; Send init checksum is always 1 char.
  479.     mov ah,'S'        ; Send initiate packet.
  480.     call spack        ; Send the packet.
  481.      jmp abort
  482.     call rpack        ; Get a packet.
  483.      jmp sini23        ; Trashed packet don't change state, retry.
  484.     push ax
  485.     mov ah,curchk
  486.     mov trans.chklen,ah    ; Checksum length we want to use.
  487.     pop ax
  488.     call acknak        ; was it ok?
  489.     cmp al,0        ; maybe an ack?
  490.     je sini22        ; yes, go handle it
  491.     cmp al,1        ; maybe a nak?
  492.     jne sinit4        ; no, check for error or something
  493.     ret            ; else just return and try again
  494. sini22:    mov ax,pack.argbk1
  495.     mov bx,offset data    ; point to data for spar
  496.     call spar        ; Read in the data.
  497.     call packlen        ; Get max send packet size. [21b]
  498.     mov ah,pack.numtry    ; Get the number of tries.
  499.     mov pack.oldtry,ah    ; Save it.
  500.     mov pack.numtry,0    ; Reset the number of tries.
  501.     mov pack.state,'F'    ; Set the state to file send.
  502.     call getfil        ; Open the file.
  503.      jmp abort        ;  Something is wrong, die.
  504.     mov filopn,1        ; Disk file is open.
  505.     ret
  506. sini23:    mov ah,curchk        ; Restore desired checksum length.
  507.     mov trans.chklen,ah
  508.     call updrtr        ; Update retry counter.
  509.     ret            ; And retry.
  510. sinit4: cmp ah,'E'        ; Is it an error packet.
  511.     jne sinit5
  512.     call error
  513. sinit5: jmp abort
  514. SINIT    ENDP
  515.  
  516.  
  517.  
  518. ;    Send file header
  519.  
  520. SFILE    PROC    NEAR
  521.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  522.     jl sfile1
  523.     call erpos
  524.     mov dx,offset erms14
  525.     mov ah,prstr
  526.     int dos            ; Print an error message.
  527.     mov bx,offset erms21
  528.     call errpack        ; Send error packet just in case.
  529.     jmp abort        ; Change the state to abort.
  530. sfile1: inc pack.numtry        ; Increment it.
  531.     mov flags.cxzflg,0    ; Clear ¬X,¬Z flag. 
  532.     mov datptr,offset data  ; Get a pointer to our data block.
  533.     mov bx,offset fcb+1        ; Pointer to file name in FCB.
  534.     mov fcbpt,bx        ; Save position in FCB.
  535.     mov cl,0        ; Counter for chars in file name.
  536.     mov ch,0        ; Counter for number of chars in FCB.
  537. sfil11:    cmp ch,8H        ; Ninth char?
  538.     jne sfil12
  539.     mov ah,'.'
  540.     mov bx,datptr
  541.     mov [bx],ah        ; Put dot in data packet.    
  542.     inc bx
  543.     mov datptr,bx        ; Save new position in data packet.
  544.     inc cl
  545. sfil12:    inc ch
  546.     cmp ch,0CH        ; Twelve?
  547.     jns sfil13
  548.     mov bx,fcbpt
  549.     mov ah,[bx]        ; Get char of filename.
  550.     inc bx
  551.     mov fcbpt,bx        ; Save position in FCB.
  552.     cmp ah,'!'        ; Is it a good char?
  553.     jl sfil11        ; If not, get the next.
  554.     mov bx,datptr
  555.     mov [bx],ah        ; Put char in data buffer.
  556.     inc cl            ; Increment counter.
  557.     inc bx
  558.     mov datptr,bx        ; Save new position. 
  559.     jmp sfil11        ; Get another char.
  560. sfil13: mov ch,0
  561.     cmp flags.remflg,0    ; remote mode?
  562.     jne sfil13a        ; yes, no printing.
  563.     push cx            ; Don't forget the size.
  564.     mov bx,datptr
  565.     mov byte ptr[bx],0    ; terminate with a null
  566.     call prtfn        ; print filename
  567.     pop cx
  568. sfil13a:cmp difnam,0        ; Sending file under different name.
  569.     je sfl13x        ; No, so don't give new name.
  570.     call newfn
  571. sfl13x:    call doenc        ; Do encoding.
  572.     mov ax,pack.pktnum    ; Get the packet number.
  573.     mov pack.argblk,ax
  574.     mov ah,'F'        ; File header packet.
  575.     call spack        ; Send the packet.
  576.      jmp abort
  577.     call rpack        ; Get a packet.
  578.      jmp tryagn        ; Trashed packet don't change state, retry.
  579.     call dodec        ; Do all decoding.
  580.     call acknak        ; see what they had to say
  581.     cmp al,0        ; ack'd ok?
  582.     je sfil14        ; yes, on to next state
  583.     cmp al,1        ; maybe a nak?
  584.     jne sfile3        ; no, check for error
  585.     ret            ; if nak, just return and try again
  586.  
  587. sfil14:    mov fcb+20h,0        ; set record number to zero
  588.     mov flags.filflg,0FFH    ; Indicate file buffer empty.
  589.     call gtchr
  590.      jmp sfil16        ; Error go see if its EOF.
  591.      nop
  592.     jmp sfil17        ; Got the chars, proceed.
  593. sfil16: cmp ah,0FFH        ; Is it EOF?
  594.     je sfl161
  595.     jmp abort        ; If not give up.
  596.  
  597. sfl161: mov ah,'Z'        ; Set the state to EOF.
  598.     mov pack.state,ah
  599.     ret
  600.  
  601. sfil17: mov siz,ax
  602.     mov pack.state,'D'    ; Set the state to data send.
  603.     ret
  604.  
  605. sfile3: cmp ah,'E'        ; Is it an error packet.
  606.     jne sfile4
  607.     call error
  608. sfile4: jmp abort
  609. SFILE    ENDP
  610.  
  611.  
  612. ;    Send data
  613.  
  614. SDATA    PROC    NEAR
  615.     cmp flags.cxzflg,0    ; Have we seen ¬X or ¬Z?
  616.     je sdata2        ; Nope, just continue.
  617.     cmp flags.cxzflg,'C'    ; Stop it all? [25]
  618.     jne sdata1        ; It was a ¬X or ¬Z.
  619.     mov pack.state,'A'    ; It was a ¬C -- abort [25]
  620.     ret
  621. sdata1:    mov pack.state,'Z'    ; Else, abort sending the file.
  622.     ret
  623. sdata2: cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  624.     jl sdata3
  625.     call erpos
  626.     mov dx,offset erms14
  627.     mov ah,prstr
  628.     int dos            ; Print an error message.
  629.     mov bx,offset erms22
  630.     call errpack        ; Send error packet just in case.
  631.     jmp abort        ; Change the state to abort.
  632. sdata3: inc pack.numtry        ; Increment it.
  633.     mov datptr,offset data  ; Get a pointer to our data block.
  634.     mov chrptr,offset filbuf ; Pointer to chars to be sent.
  635.     mov cx,siz        ; number to transfer
  636.     mov si,chrptr        ; source of characters
  637.     mov di,datptr        ; destination
  638.     rep movsb        ; just copy data
  639.     mov ax,siz        ; this is how many were moved
  640. sdata7:    mov pack.argbk1,ax
  641.     mov ax,pack.pktnum    ; Get the packet number.
  642.     mov pack.argblk,ax
  643.     mov ah,'D'        ; Data packet.
  644.     call spack        ; Send the packet.
  645.      jmp tryagn        ; if can't send it, retry before giving up
  646.     call rpack        ; Get a packet.
  647.      jmp tryagn        ; Trashed packet don't change state, retry.
  648.     call dodec        ; Do all decoding.
  649.     call acknak        ; see if ack or nak, check packet number
  650.     cmp al,0        ; 0 => ack ok, go on
  651.     je sdat11
  652.     cmp al,1        ; 1 => nak, retry count incremented, try again
  653.     jne sdat15        ; else look for other packet types...
  654.     ret            ; else return
  655.  
  656. sdat11:    cmp    pack.argbk1,1    ; any data?
  657.     jne    sdat23
  658.     mov    bl,data        ; get 1st byte
  659.     cmp    bl,'X'
  660.     je    sdat24
  661.     cmp    bl,'Y'
  662.     jne    sdat23        ; not x or y, just keep going
  663. sdat24:    mov    flags.cxzflg,bl    ; set flag appropriately
  664.     mov    pack.state,'Z'    ; simulate eof
  665.     ret            ; and return
  666.  
  667. sdat23: call gtchr
  668.      jmp sdat12        ; Error go see if its EOF.
  669.     mov siz,ax        ; Save the size of the data gotten.
  670.     ret
  671.  
  672. sdat12: cmp ah,0FFH        ; Is it EOF?
  673.     je sdat13
  674.     jmp abort        ; If not give up.
  675.  
  676. sdat13: mov pack.state,'Z'    ; Set the state to EOF.
  677.     ret
  678.  
  679. sdat15: cmp ah,'E'        ; Is it an error packet.
  680.     jne sdat16
  681.     call error
  682. sdat16: jmp abort
  683. SDATA    ENDP
  684.  
  685.  
  686. ; check the current packet for an ack or nak and handle it from any of
  687. ; the send states.  Returns: 0 if an ack received with the correct expected
  688. ; packet number, or if a nak received with the NEXT packet number (the
  689. ; packet number is incremented, retry count reset); 1 if a nak or ack
  690. ; with a bad packet number is received, retry count is updated and displayed.
  691. ; Finally, 2 is returned if anything else is seen.
  692.  
  693. ACKNAK    PROC    NEAR
  694.     cmp    ah,'Y'        ; ack packet?
  695.     jne    ackna1        ; no, keep going
  696.     mov    bx,pack.pktnum
  697.     cmp    bx,pack.argblk    ; is it what we were expecting?
  698.     jne    ackna2        ; no, update retries and punt
  699. ; packet ok, increment packet number
  700. ackna0:    mov    bx,pack.pktnum    ; reload packet number (!!!)
  701.     inc    bx
  702.     and    bx,03fh        ; increment packet number
  703.     mov    pack.pktnum,bx    ; store back
  704.     inc    pack.numpkt    ; increment # of packets
  705.     mov    bl,0
  706.     xchg    bl,pack.numtry
  707.     mov    pack.oldtry,bl    ; oldtry <- numtry, numtry <- 0
  708.     mov    al,0        ; ack'd ok
  709.     ret
  710. ; not a 'Y'...
  711. ackna1:    cmp    ah,'N'        ; a nak?
  712.     je    ackna5        ; yes, go on
  713.     mov    al,2
  714.     ret            ; unknown packet type
  715. ackna5:    mov    bx,pack.pktnum
  716.     inc    bx
  717.     and    bx,3fh
  718.     cmp    bx,pack.argblk    ; maybe a nak for pktnum+1?
  719.     je    ackna0        ; yes, treat as ack
  720. ; nak or bad ack, update retry stuff
  721. ackna2:    call rtpos        ; Position cursor.
  722.     inc pack.numrtr        ; Increment the number of retries
  723.     mov ax,pack.numrtr
  724.     call nout        ; Write the number of retries.
  725.     mov    al,1        ; nak code
  726.     ret            ; and return 
  727. ACKNAK    ENDP
  728.  
  729. ;    Send EOF
  730.  
  731. SEOF    PROC    NEAR
  732.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  733.     jl seof1
  734.     call erpos        ; Position cursor.
  735.     mov dx,offset erms14
  736.     mov ah,prstr
  737.     int dos            ; Print an error message.
  738.     mov bx,offset erms23
  739.     call errpack        ; Send error packet just in case.
  740.     jmp abort        ; Change the state to abort.
  741. seof1:  inc pack.numtry        ; Increment it.
  742.     mov ax,pack.pktnum    ; Get the packet number.
  743.     mov pack.argblk,ax
  744.     mov pack.argbk1,0    ; No data.
  745.     cmp flags.cxzflg,0    ; Seen a ¬X or ¬Z?
  746.     je seof11        ; Nope, send normal EOF packet.
  747.     mov bx,offset data    ; Get data area of packet.
  748.     mov ah,'D'        ; Use "D" for discard.
  749.     mov [bx],ah        ; And add it to the packet.
  750.     mov pack.argbk1,1    ; Set data size to 1.
  751. seof11:    mov cx,pack.argbk1    ; Put size in CX.
  752.     call doenc        ; Encode the packet.
  753.     mov ah,'Z'        ; EOF packet.
  754.     call spack        ; Send the packet.
  755.      jmp abort
  756.     call rpack        ; Get a packet.
  757.      jmp tryagn        ;  Trashed packet don't change state, retry.
  758.     call dodec        ; Do decoding.
  759.     call acknak        ; see what they had to say
  760.     cmp al,0        ; ack?
  761.     je seof12        ; yes, go close file and proceed
  762.     cmp al,1        ; maybe a nak?
  763.     jne seof3        ; no, check for error packet
  764.     ret            ; if nak, just return...
  765.  
  766. seof12:    mov ah,closf        ; Close the file.
  767.     mov dx,offset fcb
  768.     int dos
  769.     call gtnfil        ; Get the next file.
  770.      jmp seof13        ;  No more.
  771.     mov pack.state,'F'    ; Set the state to file send.
  772.     cmp flags.cxzflg,'X'    ; Control-X seen?
  773.     jne seof14
  774.     call cxmsg        ; Clear out the interrupt msg.
  775. seof14:    mov flags.cxzflg,0    ; Reset the flag.
  776.     ret
  777. seof13: mov pack.state,'B'    ; Set the state to EOT.
  778.     mov filopn,0        ; No files open.
  779.     ret
  780. seof3:  cmp ah,'E'        ; Is it an error packet?
  781.     jne seof4
  782.     call error
  783. seof4:  jmp abort
  784. SEOF    ENDP
  785.  
  786.  
  787. ;    Send EOT
  788.  
  789. SEOT    PROC    NEAR
  790.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  791.     jl seot1
  792.     call erpos           ; Position cursor.
  793.     mov dx,offset erms14
  794.     mov ah,prstr
  795.     int dos            ; Print an error message.
  796.     mov bx,offset erms24
  797.     call errpack        ; Send error packet just in case.
  798.     jmp abort        ; Change the state to abort.
  799. seot1:  inc pack.numtry        ; Increment it.
  800.     mov ax,pack.pktnum    ; Get the packet number.
  801.     mov pack.argblk,ax
  802.     mov pack.argbk1,0    ; No data.
  803.     mov cx,pack.argbk1
  804.     call doenc        ; Encode packet.
  805.     mov ah,'B'        ; EOF packet.
  806.     call spack        ; Send the packet.
  807.      jmp abort
  808.     call rpack        ; Get a packet.
  809.      jmp tryagn        ; Trashed packet don't change state, retry.
  810.     call dodec        ; Decode packet.
  811.     call acknak        ; see if good ack or nak
  812.     cmp al,0        ; ack'd ok?
  813.     je seot12        ; yes, done with this
  814.     cmp al,1        ; maybe a nak?
  815.     jne seot3        ; no, check for error
  816.     ret            ; else just return
  817. seot12:    mov pack.state,'C'    ; Set the state to file send.
  818.     ret
  819.  
  820. seot3:  cmp ah,'E'        ; Is it an error packet.
  821.     jne seot4
  822.     call error
  823. seot4:  jmp abort
  824. SEOT    ENDP
  825.  
  826. tryagn:    call updrtr
  827.     ret
  828.  
  829. newfn:    mov ah,prstr
  830.     mov dx,offset asmsg
  831.     int dos
  832.     mov ah,dconio
  833.     mov si,offset sendas    ; Buffer where the name is.
  834.     mov di,offset data
  835.     mov ch,0
  836.     mov cl,difsiz        ; Length of name.
  837. newf0:    lodsb            ; Get a char.
  838.     cmp al,61H
  839.     jb newf1        ; Leave alone if less than 'a'?
  840.     cmp al,7AH
  841.     ja newf1        ; Leave alone if over 'z'.
  842.     sub al,20H        ; Uppercase the letters.
  843. newf1:    stosb
  844.     mov dl,al
  845.     cmp flags.remflg,0    ; should we print?
  846.     jne newf2        ; no, we're in remote mode.
  847.     int dos            ; Print them.
  848. newf2:    loop newf0
  849.     mov ch,0
  850.     mov cl,difsiz        ; Reset the length field.
  851.     ret
  852.  
  853. ; Do encoding.  Expectx CX to be the data size.
  854. doenc:    jcxz doen0
  855.     mov chrcnt,cx        ; Number of chars in filename.
  856.     mov bx,offset data    ; Source of data.
  857.     mov bufpnt,bx
  858.     mov bx,offset nulref    ; Null routine for refilling buffer.
  859.     mov ah,rptq
  860.     mov origr,ah        ; Save repeat prefix here.
  861.     mov rptct,1        ; Number of times char is repeated.
  862.     mov rptval,0        ; Value of repeated char.
  863.     call encode        ; Make a packet with size in AX.
  864.      nop
  865.      nop
  866.      nop
  867.     mov pack.argbk1,ax    ; Save number of char in filename.
  868.     mov cx,ax
  869.     call movpak        ; Move to data part of packet.
  870. doen0:    ret
  871.  
  872. ; CX is set before this is called.
  873. movpak:    push es
  874.     mov ax,ds
  875.     mov es,ax
  876.     mov si,offset filbuf    ; Move from here
  877.     mov di,offset data    ; to here
  878.     repne movsb
  879.     pop es
  880.     ret
  881.  
  882. ; Do decoding.
  883. dodec:    cmp pack.argbk1,0
  884.     je dodc0
  885.     push ax            ; Save packet size.
  886.     mov cx,pack.argbk1    ; Size of data.
  887.     mov bx,offset data    ; Address of data.
  888.     mov ax,offset nulr    ; Routine to dump buffer (null routine).
  889.     mov bufpnt,offset decbuf  ; Where to put output.
  890.     mov chrcnt,80H        ; Buffer size.
  891.     call decode
  892.      nop     
  893.      nop     
  894.      nop     
  895.     call decmov        ; Move decoded data back to "data" buffer.
  896.      pop ax
  897. dodc0:    ret
  898.  
  899. ; Move decoded data from decode buffer back to "data". 
  900. decmov:    push si
  901.     push di
  902.     push es
  903.     mov ax,ds
  904.     mov es,ax
  905.     mov cx,bufpnt        ; Last char we added.
  906.     sub cx,offset decbuf    ; Get actual number of characters.
  907.     mov pack.argbk1,cx    ; Remember size of real data.
  908.     lea si,decbuf        ; Data is here.
  909.     lea di,data        ; Move to here.
  910.     repne movsb        ; Copy the data.
  911.     mov al,0        ; Null to end the string.
  912.     stosb
  913.     pop es
  914.     pop di
  915.     pop si
  916.     ret
  917.  
  918. ;    Abort
  919.  
  920. ABORT    PROC    NEAR
  921.     cmp filopn,0        ; Any disk files open?
  922.     je abort0        ; No so don't do a close.
  923.     mov ah,closf        ; Close the file and ignore errors.
  924.     mov dx,offset fcb
  925.     int dos
  926. abort0:    mov pack.state,'A'    ; Otherwise abort.
  927.     ret
  928. ABORT    ENDP
  929.  
  930. ; This is where we go if we get an error packet.  A call to ERROR 
  931. ; positions the cursor and prints the message.  A call to ERROR1
  932. ; just prints a CRLF and then the message.  [8]
  933.  
  934. ERROR    PROC    NEAR
  935.     mov pack.state,'A'    ; Set the state to abort.
  936.     call erpos        ; Position the cursor.
  937.     jmp error2
  938. error1:    mov ah,prstr
  939.     mov dx,offset crlf
  940.     int dos
  941. error2: mov bx,pack.argbk1    ; Get the length of the data.
  942.     add bx,offset data    ; Get to the end of the string.
  943.     mov ah,'$'        ; Put a dollar sign at the end.
  944.     mov [bx],ah
  945.     mov ah,prstr        ; Print the error message.
  946.     mov dx,offset data
  947.     int dos
  948.     ret
  949. ERROR    ENDP
  950.  
  951. ; Set the maximum data packet size. [21b]
  952.  
  953. PACKLEN    PROC    NEAR
  954.     mov ah,trans.spsiz    ; Maximum send packet size. 
  955.     sub ah,3        ; - sequence, type, possible #X at end
  956.     sub ah,trans.chklen    ; And minus checksum chars.
  957.     cmp trans.ebquot,'N'    ; Doing 8-bit quoting?
  958.     je pack0        ; Nope so we've got our size.
  959.     cmp trans.ebquot,'Y'
  960.     je pack0        ; Not doing it in this case either.
  961.     sub ah,1        ; Another 1 for 8th-bit quoting. 
  962. pack0:    cmp rptq,0        ; Doing repeat character quoting?
  963.     je pack1        ; Nope, so that's all for now.
  964.     sub ah,2        ; Another 2 for repeat prefix.
  965. pack1:    mov trans.maxdat,ah    ; Save max length for data field.
  966.     ret
  967. PACKLEN    ENDP
  968.  
  969.  ; Print the number in AX on the screen in decimal rather that hex. [19a]
  970.  
  971. NOUT     PROC    NEAR
  972.     cmp flags.xflg,1    ; Writing to screen? [21c]
  973.     je nout1        ; Yes, just leave. [21c]
  974.     push ax
  975.     push dx
  976.     mov temp,10        ; Divide quotient by 10.
  977.     mov dx,0        ; High order word should be zero.
  978.     div temp        ; AX <-- Quo, DX <-- Rem.
  979.     cmp ax,0        ; Are we done?    
  980.     jz nout0        ; Yes.
  981.     call nout        ; If not, then recurse.
  982. nout0:    add dl,'0'        ; Make it printable.
  983.     mov temp,ax
  984.     mov ah,conout
  985.     int dos    
  986.     mov ax,temp
  987.     pop dx
  988.     pop ax
  989. nout1:    ret            ; We're done. [21c]
  990. NOUT    ENDP
  991.  
  992. ; Jumping to this location is like retskp.  It assumes the instruction
  993. ;   after the call is a jmp addr.
  994.  
  995. RSKP    PROC    NEAR
  996.     pop bp
  997.     add bp,3
  998.     push bp
  999.     ret
  1000. RSKP    ENDP
  1001.  
  1002. ; Jumping here is the same as a ret.
  1003.  
  1004. R    PROC    NEAR
  1005.     ret
  1006. R    ENDP
  1007.  
  1008. code    ends 
  1009.     end
  1010.